import java.util.*;
import java.io.*;
import java.lang.Math.*;
import java.util.Random;

public class strop {
	
	public class alphabet {
		int alpha;
		int num;
		Hashtable freq;
		Hashtable obs;
		
		public alphabet(int a)
		{
			freq = new Hashtable();
			obs = new Hashtable();
			this.alpha = a;
			this.num = 1;
		}
		
	}
	
	Vector<alphabet> a = new Vector<alphabet>();
	Vector<Integer> txt = new Vector<Integer>();
	
	public void load_txt(String f)
	{
		try {
			int input;
			FileInputStream fstream = new FileInputStream(f);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			while ((input = br.read()) != - 1) 
				txt.add(input);
			in.close();
		} catch (Exception e) {
			System.out.println("error");
		}
	}
	
	public void get_alphabet()
	{
		int cont;
		int runs= 0;
		int prev;
		for(int i=0; i < txt.size(); i++) 
		{
			runs = 1;
			cont = 1;
			for(int j = 0; j < a.size(); j++)
			{
				if(a.elementAt(j).alpha == txt.elementAt(i)) {
					a.elementAt(j).num = a.elementAt(j).num + 1;
					cont = 0;
				}
			}
			if( cont == 1) 
				a.add(new alphabet(txt.elementAt(i)));
		}
		int k = 0;
		while(k < txt.size()-1)
		{
			runs = 0;
			prev = txt.elementAt(k);
			while(txt.elementAt(k) == txt.elementAt(k+1) && k < txt.size()-2)
			{
				runs = runs + 1;
				k = k + 1;
			}
			for(int m=0; m < a.size(); m++)
			{
				if(a.elementAt(m).alpha == prev )
				{
					if(a.elementAt(m).obs.containsKey(m) == false) 
						a.elementAt(m).obs.put(runs, 1);
					else 
						a.elementAt(m).obs.put(runs, (Integer)a.elementAt(m).obs.get(runs) + 1);

					if(a.elementAt(m).freq.containsKey(m) == false) {
						a.elementAt(m).freq.put(runs, 1);
					}
					else {
						int v = (Integer)a.elementAt(m).freq.get(runs) + 1;
						a.elementAt(m).freq.put(runs, v);
					}
				}
			}
			k = k + 1;
		}
	}
	
	public boolean freq_test(int intN)
	{
		float E = (float)intN / (float)100;
		float n = 1 / (float)(a.size() + 1);

		for(int i=0; i < a.size(); i++)
		{
			float p = (float)a.elementAt(i).num / (float)txt.size();
			if(p - E <= n && p + E >= n )
			{
				
			}
			else
				return false;
		}
		return true;
	}
	
	private int get_total_obs(int k)
	{
		int sum = 0;
		Enumeration en = a.elementAt(k).obs.keys();
		while(en.hasMoreElements())
				sum = (Integer)en.nextElement() + sum;
		return sum;
	}
	
	public boolean runs_test()
	{
		int k = 0;
		for(int i = 0; i < a.size(); i++) 
		{
			k = 0;
			while(a.elementAt(i).obs.containsKey(k))
			{
				float not_runs = 2*(float)get_total_obs(i) - (float)(Integer)a.elementAt(i).obs.get(k);
				float exp_mean = not_runs*(float)(Integer)a.elementAt(i).obs.get(k)*2;
				float exp_sd = (float)Math.sqrt( ((double)exp_mean - 1)*((double)exp_mean-2)/((double)(Integer)a.elementAt(i).obs.get(k) - 1));
				float z_score = Math.abs(((float)(Integer)a.elementAt(i).freq.get(k) - exp_mean) / exp_sd);
				if(z_score > 1.96)
					return false;
				k = k + 1;
			}
		}
		return true;
	}
	
	public boolean sums_test(int intN)
	{
		float E = (float)intN/100;
		int s = txt.size();
		float t_rev = (s*(s-1))/4;
		int count = 0;
		int sum = 0;
		for(int i = 0; i < s; i++)
		{
			count = 0;
			for(int j = i; j < s; j++)
			{
				if( txt.elementAt(i) > txt.elementAt(j))
					count = count + 1;
			}
			sum = sum + count;
		}
		float mean_dif = (float)count - t_rev + (float)0.5;
		float exp_sd = (float)Math.sqrt(((2*(double)s+5)*((double)s-1)*(double)s)/72);
		float z_score = mean_dif/exp_sd;
		if(Math.abs(z_score) > 1.96)
			return false;
		else
			return true;
	}
	
	public boolean craps_test(int intN)
	{
		int correct_guess = 0;
		float E = (float)intN / 100;
		for(int i = 0; i < txt.size(); i++)
		{
			Random r = new Random();
			//System.out.println(a.size());
			int guess = r.nextInt(a.size());
			//System.out.println(guess);
			if(txt.elementAt(i) == a.elementAt(guess).alpha)
				correct_guess = correct_guess + 1;
		}
		float percent_correct = (float)correct_guess / txt.size();
		float expected = (float)1/(float)a.size();
		if(percent_correct >= expected - E && percent_correct <= expected + E)
			return true;
		else
			return false;
	}
	
	public boolean chi_test(int intN)
	{
		float E = (float)intN / 100;
		int[] boxes = new int[10];
		float sum = 0;
		for(int i=0; i < a.size(); i++)
			boxes[i] = 0;
		for(int i=0; i < txt.size(); i++)
		{
			for(int j=0; j < a.size(); j++)
				if(a.elementAt(j).alpha == txt.elementAt(i))
					boxes[j%10] = boxes[j%10] + 1;
		}
		for(int i=0; i < 10; i++) {
			float s = (float)a.size();
			float er_est = (float)Math.pow(((float)boxes[i] - (s/(float)10)),2);
			sum = er_est + sum;
		}
		System.out.println(sum);
		return true;
		
	}
	
}
